<?php
require_once 'models/acl.inc';
require_once 'models/orm.inc';
require_once 'util/pwdgen.inc';

class TMSACL extends TCandyModel implements IACLManager {
	const SESS_CURUSER_VAR = 'current_user';
	
/** 
 * @var TMSUser
 */	
	protected $currentUser;
	
	protected $_bool_persistance_;
/**
 * @var IPasswordGenerator
 */	
	protected $_ioc_pwd_generator_;

/**
 * @var IPasswordChangeNotifier[]
 */	
	protected $_ioc_pwd_notifier_ = array();	
	
	protected function afterConstruct(){
		$this->_conf_classname_ = 'TMSUser';
	}
	
	/**
	 * checks whether specified login exists 
	 * @param string $login
	 * @return boolean
	 */
	public function UserExists($login){
		$u = new TMSUser();
		$u->Login = $login;
		return !is_null($this->Adapter->Load($u));
	}
	/**
	 * performs user authentication
	 * @param string $login user login
	 * @param string $pwd user password
	 * @return boolean
	 */
	public function Login($login,$pwd){
		$u = new TMSUser();
		$u->Login = $login;
		$u->Active = true;
		$this->currentUser = null;
		
		if ($user = $this->Adapter->Load($u,$this->AssumedDescendants)){
			if ($user->Rehashed){
				if ($user->CheckPassword($pwd))
					$this->currentUser = $user;
			} else {
				if ($user->CheckPasswordMD5($pwd)){
					$user->SetPassword($pwd);
					$this->SaveObject($user);
					$this->currentUser = $user;
				}
			}
		}
		
		if ($this->_bool_persistance_){
			$this->Application()->Session()->Set(self::SESS_CURUSER_VAR, $this->currentUser);
			$this->Application()->Session()->ResetId();
		}
		
		return ($this->currentUser instanceof TMSUser);	
	}
	
	public function ReloadProfile(){
		$this->currentUser = $this->Adapter->Load($this->currentUser,$this->AssumedDescendants);
		if ($this->_bool_persistance_)
			$this->Application()->Session()->Set(self::SESS_CURUSER_VAR, $this->currentUser);
	}
	
	/**
	 * performs user logout
	 */
	public function Logout(){
		$this->currentUser = null;
		if ($this->_bool_persistance_)
			$this->Application()->Session()->Set(self::SESS_CURUSER_VAR,null);
	}
	/**
	 * returns current logged user
	 * @return ISecuritySubject
	 */
	public function CurrentUser(){
		if ($this->_bool_persistance_)
			$this->currentUser = $this->Application()->Session()->Get(self::SESS_CURUSER_VAR);
		if ($this->currentUser instanceof TMSUser)	
			return $this->currentUser;
		return new TMSRole(TMSRole::GUEST);
	}
	
	protected function setProperty($object, $nm, $value){
		if ($nm == 'Roles'){
			$object->Roles = 0;
			$valid = TMSRole::RoleCodes();
			foreach ($value as $role)
				if (in_array($role,$valid))
					$object->Roles = $object->Roles | $role;
		} else parent::setProperty($object, $nm, $value);
	} 
	
	protected function postProcessProperties(){
		parent::postProcessProperties();
		$selection = array();
		foreach (TMSRole::RoleCodes() as $code)
			$selection[$code] = new TMSRole($code);
		$this->propertyMetas['AssignedRoles'] = new TOrmPropertyMeta('AssignedRoles','Roles',TItemPropertyType::PT_SET,$selection);
		unset($this->propertyMetas['Password']);//->Type = TItemPropertyType::PT_PASSWORD;
		unset($this->propertyMetas['Roles']);
		unset($this->propertyMetas['Rehashed']);
	}
	
	/*
	protected function postCreateItem(TCandyItem $item, array $data = array()){
		if ($this->PwdGenerator instanceof IPasswordGenerator){
			$this->RegeneratePassword($item->ItemId());
		}
	}
	*/
	protected function beforeSave(TNOrmObject $object){
		$object = parent::beforeSave($object);
		if (!$object->Email)
			throw new TCoreException(TCoreException::ERR_BAD_VALUE);
		if (!$object->Login)
			$object->Login = $object->Email;
		return $object;
	}	
	
	public function RegeneratePassword($id){
		if ($this->PwdGenerator instanceof IPasswordGenerator){
			$u = $this->GetItem($id);
			$pwd = $this->PwdGenerator->PwdGen();
			$u->Base->SetPassword($pwd);
			$this->SaveObject($u->Base);
			foreach ($this->PwdNotifier as $n)
				$n->Notify($u,$pwd);
		} else throw new TCoreException(TCoreException::ERR_BAD_VALUE);
	}
	
	public function SetPassword($id,$newpwd){
		$u = $this->GetItem($id);
		$u->Base->SetPassword($newpwd);
		return $this->SaveObject($u->Base);
	}
}